package com.wss.lsl.test.driven.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

import org.apache.commons.lang.StringUtils;

public class ZipFileUtils {

	// 10M常量
	private static final int SIZE_10M = 1024 * 1024 * 10;

	/**
	 * 压缩文件
	 * 
	 * @param inputFile
	 * @param outputFile
	 */
	public static void writeToZipFile(File inputFile, File outputFile) {
		ZipOutputStream zos = null;
		try {
			zos = new ZipOutputStream(new FileOutputStream(outputFile));
			writeToZipFile("", inputFile, zos);
		} catch (Exception e) {
			throw new RuntimeException("压缩文件发生异常", e);
		} finally {
			try {
				if (zos != null) {
					zos.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
				// ignore
			}
		}
	}

	private static void writeToZipFile(String parentName, File inputFile,
			ZipOutputStream zos) throws IOException {
		if (!StringUtils.isBlank(parentName)) {
			parentName += "/";
		}
		String thisFileName = parentName + inputFile.getName();
		System.out.println(thisFileName);
		if (inputFile.isDirectory()) {
			File[] files = inputFile.listFiles();
			if (files.length == 0) {
				// ignore: empty dir
				// 空目录不是预想的结果。 FIXME
				ZipEntry ze = new ZipEntry(thisFileName + "/");
				zos.putNextEntry(ze);
				System.out.println(ze.isDirectory());
				zos.closeEntry();
				return;
			}
			for (File file : files) {
				writeToZipFile(thisFileName, file, zos);
			}
		} else {
			zos.putNextEntry(new ZipEntry(thisFileName));
			byte[] data = new byte[SIZE_10M];
			FileInputStream fis = null;
			try {
				fis = new FileInputStream(inputFile);
				int len = 0;
				while ((len = fis.read(data)) > 0) {
					zos.write(data, 0, len);
				}
				zos.closeEntry();
			} finally {
				fis.close();
			}
		}
	}

	/**
	 * 解压文件
	 * 
	 * @param inputFile
	 *            输入的压缩文件
	 * @param outputFile
	 *            解压后输出文件的目录
	 * @throws IOException
	 * @throws ZipException
	 */
	public static void readFromZipFile(File inputFile, File outputFile)
			throws ZipException, IOException {
		// 创建输出目录
		mkdir(outputFile);

		ZipFile zfile = null;
		try {
			zfile = new ZipFile(inputFile);
			Enumeration<? extends ZipEntry> entrys = zfile.entries();
			ZipEntry entry = null;
			while (entrys.hasMoreElements()) {
				entry = entrys.nextElement();
				readFromZipFile(entry, outputFile, zfile);
			}
		} finally {
			if (zfile != null) {
				zfile.close();
			}
		}
	}

	// 将压缩的文件项写入文件
	private static void readFromZipFile(ZipEntry entry, File outputFile,
			ZipFile zfile) throws IOException {

		File currentEntryFile = new File(outputFile, entry.getName());
		if (entry.isDirectory()) {
			mkdir(currentEntryFile);
		} else {
			// 创建父级目录
			File parentDir = currentEntryFile.getParentFile();
			if (!parentDir.exists()) {
				mkdir(parentDir);
			}

			InputStream is = zfile.getInputStream(entry);
			writeToFile(is, currentEntryFile);
		}

	}

	/**
	 * 从流写文件
	 * 
	 * @param is
	 * @param currentEntryFile
	 */
	private static void writeToFile(InputStream is, File currentEntryFile)
			throws IOException {

		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		try {
			bis = new BufferedInputStream(is, SIZE_10M);
			bos = new BufferedOutputStream(new FileOutputStream(
					currentEntryFile), SIZE_10M);

			byte[] data = new byte[SIZE_10M];
			int len = 0;
			while ((len = bis.read(data)) > 0) {
				bos.write(data, 0, len);
			}
		} finally {
			if (bos != null) {
				bos.close();
			}
			if (bis != null) {
				bis.close();
			}
		}
	}

	// 创建目录
	private static void mkdir(File outputFile) {
		if (!outputFile.exists()) {
			outputFile.mkdirs();
		}
	}

}
